package ManagedBeans;

import Beans.User;
import Beans.UserInterest;
import Mail.Mail;
import dao.UserDao;
import dao.UserInterestDao;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.event.ComponentSystemEvent;
import javax.faces.model.SelectItem;
import org.joda.time.LocalDate;

/**
 @author chuck
 */
//@FacesValidator("ValidateUsernameAndPass")
@ManagedBean(name = "userManager")
@SessionScoped
public class UserManager implements Serializable {

  private User user;
  private boolean isLogged = false;//TODO check with DB if user exists
  private ArrayList<SelectItem> chiffreAnnee;
  private List<String> interetChoisi;
  private List<UserInterest> allInterestForUser;

  public User getUser() {
    return user;
  }

  public ArrayList<SelectItem> getChiffreAnnee() {
    return chiffreAnnee;
  }

  public void setChiffreAnnee(ArrayList<SelectItem> chiffreAnnee) {
    this.chiffreAnnee = chiffreAnnee;
  }

  public List<String> getInteretChoisi() {
    interetChoisi = getInterest(user.getUserID());
    return interetChoisi;
  }

  public void setInteretChoisi(List<String> interetChoisi) {

    this.interetChoisi = interetChoisi;
  }

  public List<UserInterest> getAllInterestForUser() {
    return allInterestForUser;
  }

  public void setAllInterestForUser(List<UserInterest> allInterestForUser) {

    this.allInterestForUser = allInterestForUser;
  }

  public boolean isIsLogged() {
    return isLogged;
  }

  public void setIsLogged(boolean isLogged) {
    this.isLogged = isLogged;
  }

  public void setUser(User user) {
    this.user = user;
  }

  @PostConstruct
  public void init() {
    user = new User();

    initDate();
  }

  public String logout() {
    FacesContext.getCurrentInstance().getExternalContext().invalidateSession();//TODO redirect on homepage
    return "main.xhtml?faces-redirect=true";
  }

  public String login() {
    User retrievedUser = UserDao.getByUsername(user.getUsername());

    String path = "main";//TODO redirect somewhere else
    if (retrievedUser != null) {
      if (user.getPassword().equals(retrievedUser.getPassword())) {
        isLogged = true;
        user = retrievedUser;
        String viewId = FacesContext.getCurrentInstance().getViewRoot().getViewId();//TODO check if needed and delete if not
        UserDao.updateLastLogin(user.getUserID());
        path = "gallery.xhtml?faces-redirect=true";
      } else {
        FacesMessage globalMsg = new FacesMessage("username and/or wrong password");
        FacesContext.getCurrentInstance().addMessage(null, globalMsg);
      }
    } else {
      FacesMessage globalMsg = new FacesMessage("username and/or wrong password");
      FacesContext.getCurrentInstance().addMessage(null, globalMsg);
    }

    return path;
  }

  public String createUser() {
    boolean siMailExiste = false;
    boolean siUserNameExist = false;

    //Vérification du courriel si il existe deja en bd pour avoir des user avec email unique
    if (UserDao.getEmailsByMail(user.getEmail()) == null) {
      siMailExiste = true;
    } else {
      FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Erreur, le Email existe déja!"));
      return "register";
    }

    //Vérification du userName si il existe deja en bd pour avoir des user avec userName unique
    if (UserDao.getUserName(user.getUsername()) == null) {
      siUserNameExist = true;
    } else {
      FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Erreur, le nom d'utilisateur existe déja!"));
      return "register";
    }

    if (siMailExiste == true && siUserNameExist == true) {
      UserDao.createAccount(user);
      Mail.envoyerMail("tpjava3@gmail.com", "Confirmation de votre compte", "confirmer");
      return login();
    }
    return "main";
  }

  //Recuperation des interets 
  public List<String> getInterest(int idUser) {
    //Recuperer liste des interets dans la bd
    List<UserInterest> userInterestList = UserInterestManager.getInterestForUser(idUser);
    List<String> interestList = new ArrayList<String>();

    //Transformation des idInteret int en string
    for (UserInterest uil : userInterestList) {
      String id = String.valueOf(uil.getIdInterest());
      interestList.add(id);
    }

    return interestList;
  }

  //Supprimer un compte
  public String deleteUser() {
    //Comportement si il est connecter
    if (isLogged == true) {
      int retour = UserDao.deleteAccount(new Date(0), user.getUserID());
      user = new User();
      isLogged = false;
      if (retour > 0) {
        //Message de reussite
        Mail.envoyerMail("jtanguay199@gmail.com", "Account disabled", "You have received a message from " + user.getUsername() + ".Account disabled.");
//                Mail.envoyerMail("jtanguay199@gmail.com", "Delete account", "You have received a message from " + user.getUsername() + ".Account closed.");

        FacesMessage msg = new FacesMessage("Your account is disabled until your next visit.");
        FacesContext.getCurrentInstance().addMessage(null, msg);
//        FacesMessage msg = new FacesMessage("Your account has been sucessfully closed.");
//        FacesContext.getCurrentInstance().addMessage(null, msg);

        return "main";
      } else {
        //Message d'erreur
        Mail.envoyerMail("jtanguay199@gmail.com", "Delete account error", "You have received a message from " + user.getUsername() + ".His account closure attempt fail.");

        FacesMessage msg = new FacesMessage("Error during process, a message was sent to the administrator.");
        FacesContext.getCurrentInstance().addMessage(null, msg);
      }
      //Comportement si pas connecter
    } else {
//            FacesMessage msg = new FacesMessage("You need to be connected to delete your account.");
//            FacesContext.getCurrentInstance().addMessage(null, msg);
      FacesMessage msg = new FacesMessage("You need to be connected to disabled your account.");
      FacesContext.getCurrentInstance().addMessage(null, msg);
    }

    return "login";
  }

  //Fonction pour initialiser les date pour la saisi de l'age du formulaire
  public void initDate() {
    //TODO A améliorer avec joda time pour automatiser l'affichage d'apres l'année
    chiffreAnnee = new ArrayList<>();
    for (int i = 1; i < 49; i++) {
      SelectItem j = new SelectItem(new LocalDate().getYear() - 18 - i);
      chiffreAnnee.add(j);
    }
  }

  //Mise a jour du profil d'un user
  public String updateAUser() {
    //Updater si il est connecter
    if (isLogged == true) {
      int update = UserDao.updateUser(user.getIsWarnedByEmail(), user.getIsWarnedAddWatchList(), user.getPassword(), user.getCity(), user.getAge(), user.getLookingForSex(), user.getSex(), user.getHeight(), user.getGoal(), user.getResume(), user.getApparence(), user.getUserID());
      interestManage();

      if (update > 0) {
        //Message de reussite
        FacesMessage msg = new FacesMessage("Your update has been successful.");
        FacesContext.getCurrentInstance().addMessage(null, msg);

        return "profile";
      } else {
        //Message d'erreur
        Mail.envoyerMail("jtanguay199@gmail.com", "Update account error", "You have received a message from " + user.getUsername() + " .His account update attempt fail.");

        FacesMessage msg = new FacesMessage("Error during process, a message was sent to the administrator.");
        FacesContext.getCurrentInstance().addMessage(null, msg);
      }
    }
    return "updateProfile";
  }

  //Update d'un profil
  public String upgradeAccount() {
    //Comportement si il est connecter et est membre privilegier
    if (isLogged == true && user.getIsPrivileged() == true) {
      FacesMessage msg = new FacesMessage("You already upgrade your account.");
      FacesContext.getCurrentInstance().addMessage(null, msg);
      //Comportement si il est connecter et pas membre privilegier 
    } else if (isLogged == true && user.getIsPrivileged() == false) {
      int nbModification = UserDao.upgradeUserAccount(true, user.getUserID());

      if (nbModification > 0) {
        //Message de reussite
        Mail.envoyerMail("jtanguay199@gmail.com", "Upgrade account", "You have received a message from " + user.getUsername() + ".He is now a privileged member.");

        user.setIsPrivileged(true);
        FacesMessage msg = new FacesMessage("Your account will be sucessfully upgrade.");
        FacesContext.getCurrentInstance().addMessage(null, msg);

        return "profile";
      } else {
        //Message d'erreur
        Mail.envoyerMail("jtanguay199@gmail.com", "Upgrade account", "You have received a message from " + user.getUsername() + ".His account upgrade attempt fail");

        FacesMessage msg = new FacesMessage("Error during process, a message was sent to the administrator.");
        FacesContext.getCurrentInstance().addMessage(null, msg);
      }
      //Comportement si il est deconnecter
    } else if (isLogged == false) {
      FacesMessage msg = new FacesMessage("You need to be connected to upgrade your account.");
      FacesContext.getCurrentInstance().addMessage(null, msg);
    }
    return "payPal";
  }

  //Gestion des interets
  public void interestManage() {
    //Recuperation des interet du user dans la bd
    allInterestForUser = new ArrayList<UserInterest>();
    allInterestForUser = UserInterestDao.getAllInterestForUser(user.getUserID());

    if ((!interetChoisi.isEmpty()) && (!allInterestForUser.isEmpty())) {
      //Boucle pour delete les interet 
      for (UserInterest ui : allInterestForUser) {
        UserInterestManager.deleteInterestForUser(user.getUserID(), ui.getIdInterest());
      }

      //Boucle pour insert les interet
      for (String s : interetChoisi) {
        int i = Integer.parseInt(s);

        UserInterestManager.insertInterestForUser(user.getUserID(), i);
      }
    } else if (allInterestForUser.isEmpty() && !interetChoisi.isEmpty()) {
      for (String s : interetChoisi) {

        int i = Integer.parseInt(s);

        UserInterestDao.insertAnInterest(user.getUserID(), i);
      }
    }
  }

  //Methode de validation post validation pour la validation du 2e mot de passe
  public void validatePassword(ComponentSystemEvent event) {

    FacesContext fc = FacesContext.getCurrentInstance();

    UIComponent components = event.getComponent();

    //Recuperation du password
    UIInput uiInputPassword = (UIInput) components.findComponent("newPasswordUpdateInput");
    String password = uiInputPassword.getLocalValue() == null ? ""
            : uiInputPassword.getLocalValue().toString();
    String passwordId = uiInputPassword.getClientId();

    //Recuperation du password confirm
    UIInput uiInputConfirmPassword = (UIInput) components.findComponent("newPasswordAgainUpdateInput");
    String confirmPassword = uiInputConfirmPassword.getLocalValue() == null ? ""
            : uiInputConfirmPassword.getLocalValue().toString();

    //Verification si le champ password est rempli
    if (password.isEmpty()) {
      FacesMessage msg = new FacesMessage("The password is required.");
      msg.setSeverity(FacesMessage.SEVERITY_ERROR);
      fc.addMessage(passwordId, msg);
      fc.renderResponse();
    }
    //Verification si le les 2 password sont pareil
    if (!password.equals(confirmPassword)) {

      FacesMessage msg = new FacesMessage("Password must match confirm password.");
      msg.setSeverity(FacesMessage.SEVERITY_ERROR);
      fc.addMessage(passwordId, msg);
      fc.renderResponse();
    }
  }

  //recuperer profil pour un favori
  public User getFavoriteUser(int idUser) {
    User u = UserDao.getUserById(idUser);
    return u;
  }

  public void forwardToLoginIfNotLoggedIn() {
    FacesContext faceCtx = FacesContext.getCurrentInstance();
    String viewId = faceCtx.getViewRoot().getViewId();
    if (!isLogged && (!viewId.startsWith("/main") && !viewId.startsWith("/register"))) {
      faceCtx.getApplication().getNavigationHandler().handleNavigation(faceCtx, null, "/main?faces-redirect=true");
    } else if (isLogged && (viewId.startsWith("/main") || viewId.startsWith("/register") || viewId.startsWith("/login"))) {
      faceCtx.getApplication().getNavigationHandler().handleNavigation(faceCtx, null, "/gallery?faces-redirect=true");
    }
  }
}
